////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBotUnitTests\TestGeometricMeanTreeNode.h
///
/// @brief  Defines the tests for CollabRC::Bot::AI::GeometricMeanTreeNode
////////////////////////////////////////////////////////////////////////////////////////////////////

#include <cxxtest/TestSuite.h>
#include "../CollabRCBot/GeometricMeanTreeNode.h"
#include "MockOperationTreeNode.h"
#include "MockConstantTreeNode.h"
#include "../CollabRCBot/exceptions.h"

class TestGeometricMeanTreeNode : public CxxTest::TestSuite
{
private:
    MockConstantTreeNode m_lhs, m_rhs;
public:
    TestGeometricMeanTreeNode():m_lhs(2),m_rhs(8) { };
    
    /**
     * @brief Tests the PerformOperation() method of a GeometricMeanTreeNode
     */
    void TestPerformOperation()
    {
        CollabRC::Bot::AI::GeometricMeanTreeNode node(m_lhs, m_rhs);
        TS_ASSERT_EQUALS(node.PerformOperation(2.0f, 8.0f), 4.0f);
        TS_ASSERT_EQUALS(node.PerformOperation(8.0f, 2.0f), 4.0f);
        TS_ASSERT_EQUALS(node.PerformOperation(0.0f, 1.0f), 0.0f);
        TS_ASSERT_EQUALS(node.PerformOperation(1.0f, 0.0f), 0.0f);
        TS_ASSERT_EQUALS(node.PerformOperation(0.0f, 0.0f), 0.0f);

        // Negative values are illegal
        TS_ASSERT_THROWS(node.PerformOperation(-1.0f, 1.0f), const CollabRC::Bot::AI::IllegalOperationException&);
        TS_ASSERT_THROWS(node.PerformOperation(1.0f, -1.0f), const CollabRC::Bot::AI::IllegalOperationException&);
        TS_ASSERT_THROWS(node.PerformOperation(-1.0f, -1.0f), const CollabRC::Bot::AI::IllegalOperationException&);
    }

    /** @brief Tests the Clone() method of a GeometricMeanTreeNode */
    void TestClone()
    {
        CollabRC::Bot::AI::GeometricMeanTreeNode node(m_lhs, m_rhs);
        CollabRC::Bot::AI::ComputationalTreeNode *clone = node.Clone();
        TS_ASSERT_EQUALS(node.Compute(), clone->Compute());
        TS_ASSERT_THROWS_NOTHING(delete clone);
    }

    /** 
     * @brief Tests the ability to mutate to a GeometricMeanTreeNode from
     * another operation node
     */
    void TestMutation()
    {
        MockOperationTreeNode mock(m_lhs, m_rhs);
        CollabRC::Bot::AI::GeometricMeanTreeNode mutation(mock);
        TS_ASSERT_EQUALS(mutation.Compute(), mutation.PerformOperation(m_lhs.Compute(), m_rhs.Compute()));
    }

};